package com.wmh.baseservice.user.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wmh.baseservice.common.ex.ServiceException;
import com.wmh.baseservice.common.mybatisplus.methods.CommonServiceImpl;
import com.wmh.baseservice.common.utils.UUIDUtil;
import com.wmh.baseservice.merchant.pojo.MerchantActivity;
import com.wmh.baseservice.merchant.pojo.MerchantInfo;
import com.wmh.baseservice.merchant.service.MerchantActivityService;
import com.wmh.baseservice.merchant.service.MerchantInfoService;
import com.wmh.baseservice.system.pojo.SysMessage;
import com.wmh.baseservice.system.service.SysMessageService;
import com.wmh.baseservice.user.mapper.UsActivityRegisterMapper;
import com.wmh.baseservice.user.pojo.UsActivityRegister;
import com.wmh.baseservice.user.pojo.UsIncomeExpend;
import com.wmh.baseservice.user.pojo.UsInfo;
import com.wmh.baseservice.user.service.UsActivityRegisterService;
import com.wmh.baseservice.user.service.UsIncomeExpendService;
import com.wmh.baseservice.user.service.UsInfoService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * @author wmh generator
 * @since 2022-04-09
 */
@Service
public class UsActivityRegisterServiceImpl extends CommonServiceImpl<UsActivityRegisterMapper, UsActivityRegister> implements UsActivityRegisterService {

    @Resource
    private UsInfoService usInfoService;
    @Resource
    private UsIncomeExpendService usIncomeExpendService;
    @Resource
    private SysMessageService sysMessageService;
    @Resource
    private MerchantInfoService merchantInfoService;
    @Resource
    private MerchantActivityService merchantActivityService;


    @Override
    @Transactional(rollbackFor = Exception.class)
    public void payBalance(MerchantActivity merchantActivity, UsInfo usInfo) {
        //修改用户余额
        usInfo.setBalance(usInfo.getBalance().subtract(merchantActivity.getCost()));
        if (!usInfoService.updateById(usInfo)) {
            throw new ServiceException(usInfo.toString());
        }
        //用户支出记录
        UsIncomeExpend usIncomeExpend = new UsIncomeExpend().setUsId(usInfo.getId()).setMoney(merchantActivity.getCost()).setRemark("活动报名费").setStatus(-1).setType(1);
        if (!usIncomeExpendService.save(usIncomeExpend)) {
            throw new ServiceException(usIncomeExpend.toString());
        }
        // 保存商家收入记录
        merchantActivityService.saveIncomeExpend(merchantActivity, 1);
        // 报名活动
        register(merchantActivity, usInfo, 1, 1);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String register(MerchantActivity merchantActivity, UsInfo usInfo, Integer method, Integer nowStatus) {
        if (merchantActivity == null) {
            throw new ServiceException("报名失败 : 活动信息丢失. 请重试或联系管理员");
        }
        if (usInfo == null) {
            throw new ServiceException("报名失败 : 用户信息丢失. 请重试或联系管理员");
        }
        if (method != 1 && method != 0) {
            throw new ServiceException("报名失败 : 不支持的报名方式");
        }
        //查询是否已到报名时间
        merchantActivityService.signUpTimeCheck("报名失败 :", merchantActivity);

        // 判断报名方式是否与活动支持的报名方式一致
        if (!merchantActivity.getHasCost().equals(method)) {
            throw new ServiceException("报名失败 : 报名方式与活动支持的报名方式不一致");
        }


        UsActivityRegister usRegisterInfo = getOneForUpdate(
                new QueryWrapper<UsActivityRegister>()
                        .eq(UsActivityRegister.US_ID, usInfo.getId())
                        .eq(UsActivityRegister.ACTIVITY_ID, merchantActivity.getId())
                        .in(UsActivityRegister.STATUS, 0, 1, 2));
        /* 判断用户是否已经报名 */
        if (usRegisterInfo != null && usRegisterInfo.getStatus() != 0) {
            throw new ServiceException("报名失败 : 您已经报名");
        }
        /* 判断是报名人数是否已满 */
        if (merchantActivity.getRegisterCount() != -1) {
            int registerCount = count(
                    new QueryWrapper<UsActivityRegister>()
                            .eq(UsActivityRegister.ACTIVITY_ID, merchantActivity.getId())
                            .in(UsActivityRegister.STATUS, 0, 1));
            // 如果用户已经报名则报名人数预计值不再加 1
            registerCount = usRegisterInfo != null ? registerCount : registerCount + 1;
            if (registerCount > merchantActivity.getRegisterCount()) {
                throw new ServiceException("报名失败 : 当前活动报名人数已满，请晚一点再来尝试");
            }
        }
        UsActivityRegister newRegisterInfo = null;
        // 用户还没有报名设置新值
        if (usRegisterInfo == null){
            newRegisterInfo = new UsActivityRegister()
                    .setActivityId(merchantActivity.getId())
                    .setUsId(usInfo.getId())
                    .setStatus(nowStatus)
                    .setMerchantId(merchantActivity.getMerchantId())
                    .setOrderNum(UUIDUtil.getTimeId() + UUIDUtil.getLetter());
        } else {
            // 用户已经报名但未支付 只修改状态为新状态
            newRegisterInfo = usRegisterInfo.setStatus(nowStatus);
        }

        if (!saveOrUpdate(newRegisterInfo)) {
            throw new ServiceException(newRegisterInfo.toString());
        }
        if (nowStatus == 1) {
            sendMessage(merchantActivity, usInfo, newRegisterInfo);
        }
        return newRegisterInfo.getOrderNum();
    }


    @Override
    public void cancelSignUp(Long registerId) {
        UsActivityRegister register = getByIdForUpdate(registerId);
        if (register == null) {
            throw new ServiceException("申请取消报名失败 : 报名记录丢失,请重试或联系管理员");
        }
        if (!updateById(register.setStatus(-1))) {
            throw new ServiceException("申请取消报名失败 : 系统异常,请重试或联系管理员");
        }
    }

    @Override
    public JSONObject wechatPaySignUpCommitCheck(String orderNum) {
        String errMsgPrefix = "申请微信支付失败 : ";
        UsActivityRegister registerInfo = getOneForUpdate(
                new QueryWrapper<UsActivityRegister>()
                        .eq(UsActivityRegister.ORDER_NUM, orderNum)
        );
        if (registerInfo == null) {
            throw new ServiceException(errMsgPrefix + "活动报名记录丢失,请尝试重试或联系管理员");
        }
        MerchantActivity activityInfo = merchantActivityService.getByIdForUpdate(registerInfo.getActivityId());
        if (activityInfo == null) {
            throw new ServiceException(errMsgPrefix + "活动信息丢失,请尝试重试或联系管理员");
        }
        if (registerInfo.getStatus() != 0) {
            throw new ServiceException(errMsgPrefix + "活动报名状态错误, 请尝试重试或联系管理员");
        }
        JSONObject result = new JSONObject(true);
        result.put("money", activityInfo.getCost());
        return result;
    }

    @Override
    public void wechatPaySignUpComplete(String orderNum) {
        String errMsgPrefix = "活动报名-微信支付完成-回调失败 : ";
        UsActivityRegister registerInfo = getOneForUpdate(
                new QueryWrapper<UsActivityRegister>()
                        .eq(UsActivityRegister.ORDER_NUM, orderNum)
        );
        if (registerInfo == null) {
            throw new ServiceException(errMsgPrefix + "不存在的报名记录 订单号  : " + orderNum);
        }
        Long activityId = registerInfo.getActivityId();
        MerchantActivity activityInfo = merchantActivityService.getByIdForUpdate(activityId);
        if (activityInfo == null) {
            throw new ServiceException(errMsgPrefix + "不存在的活动  Activity ID : " + activityId);
        }
        Long merchantId = registerInfo.getMerchantId();
        MerchantInfo merchantInfo = merchantInfoService.getByIdForUpdate(merchantId);
        if (merchantInfo == null) {
            throw new ServiceException(errMsgPrefix + "不存在的商家  Merchant ID : " + merchantId);
        }
        Long usId = registerInfo.getUsId();
        UsInfo usInfo = usInfoService.getByIdForUpdate(usId);
        if (usInfo == null) {
            throw new ServiceException(errMsgPrefix + "不存在的用户  UsInfo ID : " + usId);
        }
        //用户支出记录
        UsIncomeExpend usIncomeExpend = new UsIncomeExpend().setUsId(usInfo.getId()).setMoney(activityInfo.getCost()).setRemark("活动报名费").setStatus(-1).setType(1);
        if (!usIncomeExpendService.save(usIncomeExpend)) {
            throw new ServiceException(usIncomeExpend.toString());
        }
        // 保存商家收入记录
        merchantActivityService.saveIncomeExpend(activityInfo, 1);
        // 发送相关消息
        sendMessage(activityInfo, usInfo, registerInfo);

        // 设置状态为已报名
        if (!updateById(registerInfo.setStatus(1))) {
            throw new ServiceException(errMsgPrefix + " 修改报名状态为 已报名失败  usId : " + usId + " merchantId : " + merchantId + " activityId : " + activityId);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void sendMessage(MerchantActivity merchantActivity, UsInfo usInfo, UsActivityRegister usRegisterInfo) {
        /*  对用户和商家发送相关信息, 并保存报名信息   */
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH点mm分ss秒");
        SysMessage sysMessage = new SysMessage();
        sysMessage.setUsId(usRegisterInfo.getUsId()).setTitle(String.format("您已成功报名%s", merchantActivity.getTitle()))
                .setContent(String.format("活动将于%s在%s举行，请按时到达现场后在小程序内签到喔", simpleDateFormat.format(merchantActivity.getOpenTime()), merchantActivity.getAddress()));
        if (!sysMessageService.save(sysMessage)) {
            throw new ServiceException(sysMessage.toString());
        }
        sysMessage = new SysMessage();
        sysMessage.setMerchantId(merchantActivity.getMerchantId()).setTitle(String.format("有用户报名了%s", merchantActivity.getTitle()))
                .setContent(String.format("用户%s于%s成功报名了%s", usInfo.getNick(), simpleDateFormat.format(new Date()), merchantActivity.getTitle()));
        if (!sysMessageService.save(sysMessage)) {
            throw new ServiceException(sysMessage.toString());
        }
    }
}
